<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2048 Game</title>
    <style>
      body {
        font-family: 'avenir', sans-serif;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        margin: 0;
        background-color: #ffffff;
      }

      .container {
        text-align: center;
      }

      h1 {
        color: #333;
        font-size: 1.5em;
      }

      .grid {
        display: grid;
        grid-template-columns: repeat(4, 60px);
        grid-template-rows: repeat(4, 60px);
        gap: 6px;
        background-color: #ffe2b5;
        padding: 12px;
        border-radius: 10px;
        margin: 20px auto;
      }

      .cell {
        width: 60px;
        height: 60px;
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: #eee;
        color: #333;
        font-weight: bold;
        border-radius: 3px;
        font-size: 20px;
      }

      .cell.empty {
        background-color: #ccc;
      }

      /* Tile colors */
      .tile-2 {
        background-color: #eee4da;
      }
      .tile-4 {
        background-color: #ede0c8;
      }
      .tile-8 {
        background-color: #f2b179;
        color: #f9f6f2;
      }
      .tile-16 {
        background-color: #f59563;
        color: #f9f6f2;
      }
      .tile-32 {
        background-color: #f67c5f;
        color: #f9f6f2;
      }
      .tile-64 {
        background-color: #f65e3b;
        color: #f9f6f2;
      }
      .tile-128 {
        background-color: #edcf72;
        color: #f9f6f2;
        font-size: 18px;
      }
      .tile-256 {
        background-color: #edcc61;
        color: #f9f6f2;
        font-size: 18px;
      }
      .tile-512 {
        background-color: #edc850;
        color: #f9f6f2;
        font-size: 18px;
      }
      .tile-1024 {
        background-color: #edc53f;
        color: #f9f6f2;
        font-size: 14px;
      }
      .tile-2048 {
        background-color: #edc22e;
        color: #f9f6f2;
        font-size: 14px;
      }

      .button-container {
        display: flex;
        justify-content: center;
        gap: 3px;
        margin-top: 20px;
      }

      button {
        background-color: #f57c00;
        color: white;
        border: none;
        padding: 10px 15px;
        font-size: 10px;
        font-family: 'avenir', sans-serif;
        cursor: pointer;
        border-radius: 4px;
        transition: background-color 0.3s, transform 0.2s;
      }

      button:hover {
        background-color: #fb8c00;
        transform: scale(1.05);
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>2048 Game</h1>
      <div class="grid" id="grid"></div>
      <div class="button-container">
        <button id="up">Up</button>
        <button id="down">Down</button>
        <button id="left">Left</button>
        <button id="right">Right</button>
      </div>
    </div>

    <script>
      const gridSize = 4
      let grid = Array(gridSize)
        .fill()
        .map(() => Array(gridSize).fill(0))
      const gridContainer = document.getElementById('grid')

      // Initialize the game
      function initGame() {
        addRandomTile()
        addRandomTile()
        render()
      }

      // Add a random tile to the grid
      function addRandomTile() {
        const emptyCells = []
        for (let r = 0; r < gridSize; r++) {
          for (let c = 0; c < gridSize; c++) {
            if (grid[r][c] === 0) {
              emptyCells.push({ r, c })
            }
          }
        }
        if (emptyCells.length > 0) {
          const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]
          grid[randomCell.r][randomCell.c] = Math.random() < 0.9 ? 2 : 4
        }
      }

      // Render the grid
      function render() {
        gridContainer.innerHTML = ''
        for (let r = 0; r < gridSize; r++) {
          for (let c = 0; c < gridSize; c++) {
            const cell = document.createElement('div')
            cell.className = 'cell'
            const value = grid[r][c]
            if (value !== 0) {
              cell.textContent = value
              cell.classList.add(`tile-${value}`)
            } else {
              cell.classList.add('empty')
            }
            gridContainer.appendChild(cell)
          }
        }
      }

      // Merge cells in a row/column
      function mergeCells(line) {
        // Remove zeros
        let filteredLine = line.filter(val => val !== 0)
        let mergedLine = []
        let skip = false

        for (let i = 0; i < filteredLine.length; i++) {
          if (skip) {
            skip = false
            continue
          }
          if (i + 1 < filteredLine.length && filteredLine[i] === filteredLine[i + 1]) {
            mergedLine.push(filteredLine[i] * 2)
            skip = true // Skip the next element as it's merged
          } else {
            mergedLine.push(filteredLine[i])
          }
        }

        // Pad with zeros to make it length 4
        while (mergedLine.length < gridSize) {
          mergedLine.push(0)
        }
        return mergedLine
      }

      // Move tiles in a given direction
      function move(direction) {
        let moved = false
        let newGrid = JSON.parse(JSON.stringify(grid)) // Deep copy

        if (direction === 'left') {
          for (let r = 0; r < gridSize; r++) {
            let originalRow = [...grid[r]]
            let newRow = mergeCells(originalRow)
            newGrid[r] = newRow
            // Check if row changed
            for (let c = 0; c < gridSize; c++) {
              if (originalRow[c] !== newRow[c]) {
                moved = true
                break
              }
            }
          }
        } else if (direction === 'right') {
          for (let r = 0; r < gridSize; r++) {
            let originalRow = [...grid[r]]
            let reversedRow = originalRow.reverse()
            let mergedReversedRow = mergeCells(reversedRow)
            let newRow = mergedReversedRow.reverse()
            newGrid[r] = newRow
            // Check if row changed
            for (let c = 0; c < gridSize; c++) {
              if (originalRow[c] !== newRow[c]) {
                moved = true
                break
              }
            }
          }
        } else if (direction === 'up') {
          for (let c = 0; c < gridSize; c++) {
            let originalColumn = grid.map(row => row[c])
            let newColumn = mergeCells(originalColumn)
            for (let r = 0; r < gridSize; r++) {
              newGrid[r][c] = newColumn[r]
            }
            // Check if column changed
            for (let r = 0; r < gridSize; r++) {
              if (originalColumn[r] !== newColumn[r]) {
                moved = true
                break
              }
            }
          }
        } else if (direction === 'down') {
          for (let c = 0; c < gridSize; c++) {
            let originalColumn = grid.map(row => row[c])
            let reversedColumn = originalColumn.reverse()
            let mergedReversedColumn = mergeCells(reversedColumn)
            let newColumn = mergedReversedColumn.reverse()
            for (let r = 0; r < gridSize; r++) {
              newGrid[r][c] = newColumn[r]
            }
            // Check if column changed
            for (let r = 0; r < gridSize; r++) {
              if (originalColumn[r] !== newColumn[r]) {
                moved = true
                break
              }
            }
          }
        }

        if (moved) {
          grid = newGrid
          addRandomTile()
          render()
          if (checkGameOver()) {
            setTimeout(() => alert('Game Over!'), 100) // Slight delay for render
          }
        }
      }

      // Check if the game is over
      function checkGameOver() {
        // Check for empty cells
        for (let r = 0; r < gridSize; r++) {
          for (let c = 0; c < gridSize; c++) {
            if (grid[r][c] === 0) {
              return false
            }
          }
        }

        // Check for possible merges horizontally and vertically
        for (let r = 0; r < gridSize; r++) {
          for (let c = 0; c < gridSize; c++) {
            const current = grid[r][c]
            if ((c < gridSize - 1 && current === grid[r][c + 1]) || (r < gridSize - 1 && current === grid[r + 1][c])) {
              return false
            }
          }
        }

        return true
      }

      // Event listeners for buttons
      document.getElementById('up').addEventListener('click', () => move('up'))
      document.getElementById('down').addEventListener('click', () => move('down'))
      document.getElementById('left').addEventListener('click', () => move('left'))
      document.getElementById('right').addEventListener('click', () => move('right'))

      // Initialize the game on load
      window.onload = initGame
    </script>
  </body>
</html>
